package zhongbo.java.air.monitor.listener;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import zhongbo.java.air.monitor.Service.IJtsService;
import zhongbo.java.air.monitor.mapper.AirAlertLogMapper;
import zhongbo.java.air.monitor.model.AirAlertLog;
import zhongbo.java.air.monitor.model.dto.AlertZoneDto;
import zhongbo.java.air.monitor.model.dto.PointDto;
import zhongbo.java.air.monitor.websocket.AlertZoneWebSocket;
import zhongbo.java.air.monitor.websocket.WebsocketServer;

import javax.websocket.Session;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;


@Component
public class RedisSubscribeLogChanelListener implements MessageListener {

    private static final String ALERT_USERS_KEY = "alert:history:tang_guo_zheng:icao,";

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private AirAlertLogMapper airAlertLogMapper;

    @Autowired
    private IJtsService iJtsService;


    /**
     * 接受广播消息
     * @param message
     * @param bytes
     */
    @Override
    public void onMessage(Message message, byte[] bytes) {
        String msg = redisTemplate.getStringSerializer().deserialize(message.getBody());

        /**
         * 转换为json
         */
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String json = objectMapper.readTree(msg).asText();
            System.out.println(json);

            /**
             * 发送信息
             */
            Set<Map.Entry<String, Session>> entries = WebsocketServer.SessionMap.entrySet();
            for (Map.Entry<String, Session> entry : entries) {
                entry.getValue().getBasicRemote().sendText(json);
            }


            /**
             * 判断是否有数据
             */
            JSONObject jsonObject = JSONUtil.parseObj(json);
            if (jsonObject.isEmpty()){
                System.out.println("没有数据");
                return;
            }


            /**
             * 查询区域数据
             */
            List<AlertZoneDto> airAlertZoneList = airAlertLogMapper.getAirAlertZoneSize();
            if (!(airAlertZoneList.size() > 0)){
                return;
            }

            /***
             * 判断5分钟内是否有警告日志
             */

              String icaoCode = (String) jsonObject.getObj("icaoCode");
            /***
             * 查询数据方法判断五分至是否有警告
             */
//            QueryWrapper<AirAlertLog> queryWrapper = new QueryWrapper<>();
//            queryWrapper.eq("icao_code", icaoCode);
//            Calendar beforeTime  = Calendar.getInstance();
//            beforeTime.add(Calendar.MINUTE, -5);
//            queryWrapper.le("trigger_time", beforeTime.getTime().toString());
//            if (!airAlertLogMapper.selectList(queryWrapper).isEmpty()){
//                System.out.println("五分钟内已有警告");
//                return;
//            }

            /**
             * redis查询
             */
            Map<Object, Object> airAlertLogMap = redisTemplate.opsForHash().entries(ALERT_USERS_KEY);
            if (airAlertLogMap.get(icaoCode) != null){
                System.out.println("五分钟内已有警告");
                return;
            }


            BigDecimal latitude = (BigDecimal) jsonObject.getObj("latitude");
            BigDecimal longitude = (BigDecimal) jsonObject.getObj("longitude");

            /**
             * 判断是否需要发送警告
             */
            for (AlertZoneDto alertZoneDto : airAlertZoneList) {
                List<PointDto> pointDtoList = iJtsService.parseAlertZoneVertices(alertZoneDto.getVertices());

                boolean inAlertZone =
                        iJtsService.isInAlertZone(pointDtoList, longitude.doubleValue(), latitude.doubleValue());

                if (inAlertZone){
                    AirAlertLog airAlertLog = new AirAlertLog();
                    /**
                     * 填充字段
                     */
                    airAlertLog.setAlertZoneId(alertZoneDto.getId());
                    airAlertLog.setIcaoCode(icaoCode);
                    airAlertLog.setAlertType(alertZoneDto.getZoneType());
                    airAlertLog.setTriggerCoordinates(alertZoneDto.getVertices());
                    airAlertLog.setTriggerTime(new Date());
                    airAlertLog.setId(UUID.randomUUID().toString());
                    airAlertLog.setAlertZoneCode(alertZoneDto.getZoneCode());
                    airAlertLog.setCreateTime(new Date());
                    airAlertLog.setUpdateTime(new Date());


                    /**
                     * 添加到数据库
                     */
//                    airAlertLogMapper.insert(airAlertLog);

                    /**
                     * 缓存到redis
                     */
                    redisTemplate.opsForHash().put(ALERT_USERS_KEY,icaoCode,airAlertLog);
                    //设置过期时间
                    redisTemplate.expire(ALERT_USERS_KEY,1, TimeUnit.MINUTES);


                    String airAlertLogText = objectMapper.writeValueAsString(airAlertLog);
                    JSONObject jsonAirAlertLog = JSONUtil.parseObj(airAlertLogText);
                    jsonAirAlertLog.set("triggerTime",new Date().getTime());
                    System.out.println("警告消息：" + jsonAirAlertLog.toString());
                    /**
                     * 发送信息
                     */
                    Set<Map.Entry<String, Session>> alertZone = AlertZoneWebSocket.SessionMap.entrySet();
                    for (Map.Entry<String, Session> entry : alertZone) {
                        entry.getValue().getBasicRemote().sendText(jsonAirAlertLog.toString());
                    }
                }
            }



        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
